package com.zkyc.framework.file.service;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.zkyc.framework.common.constant.Constant;
import com.zkyc.framework.common.constant.MinioConstant;
import com.zkyc.framework.common.constant.NumberConstant;
import com.zkyc.framework.common.mapper.FileMapper;
import com.zkyc.framework.common.pojo.File;
import com.zkyc.framework.common.pojo.User;
import com.zkyc.framework.common.pojo.Website;
import com.zkyc.framework.file.client.WebsiteClient;
import com.zkyc.framework.file.util.*;
import com.zkyc.framework.common.utils.WebsiteUtil;
import com.zkyc.framework.common.vo.ResultVO;
import com.zkyc.framework.file.client.UserClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import static com.zkyc.framework.file.util.ImageUtils.getImgWH;

/**
 * MinIoService
 *
 * @version 1.0
 */
@Service
@Slf4j
public class MinIoService {


    public static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(5, 50, 300, TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(50));
    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private UserClient userClient;

    @Autowired
    private WebsiteClient websiteClient;

    @Value("${minio.bucket}")
    private String bucket;
    @Value("${minio.url}")
    private String domain_url;
    @Value("${minio.url_prefix}")
    private String url_prefix;

    @Value("${zjlab.logo}")
    private String logo;

    /**
     * Minio下载文件
     */
    public void download(String fileName, String filePath) throws Exception {
        MinioUtils.download(bucket, fileName, filePath, null);
    }

    /**
     * 文件下载
     *
     * @param response
     * @param url
     */
    public void download(HttpServletResponse response, String url) {
        // 从链接中得到文件名
        String replace = url.replace(bucket + "/", "#");
        String fileName = replace.split("#")[1];
        InputStream inputStream;
        try {
            inputStream = MinioUtils.getInputStream(bucket, fileName);
            response.setContentType("application/force-download");
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            IOUtils.copy(inputStream, response.getOutputStream());
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     *
     * @return
     * @throws Exception Exception
     */

    public JSONObject upload(HttpServletRequest request, String belongKey) throws Exception {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        UploadVerify.uploadVerify(file);
        String fileName = file.getOriginalFilename();
        Integer height = 0;
        if (ImageUtils.isImage(fileName)) {
            BufferedImage image = ImageIO.read(file.getInputStream());
            height = image.getHeight();
        }
        System.out.println(fileName);
        String objectKey = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."));
        // 把文件放到minio的boots桶里面
        MinioUtils.uploadInputStream(bucket, objectKey, file);
        //判断封面图片是否需要压缩
        boolean isCompress = file.getSize() > 1002000;
        return getFile(belongKey, fileName, objectKey, height, WebsiteUtil.getWebsiteId(), isCompress);
    }

    private JSONObject getFile(String belongKey, String fileName, String objectKey, Integer height, String websiteId, boolean isCompress) throws Exception {
        String cover = UUID.randomUUID() + ".jpg";
        String watermark = UUID.randomUUID() + ".jpg";
        JSONObject jsonObject = new JSONObject();
        // threadPool.execute(new FileUploadThread(bucket, objectKey, multipartRequest));
        //String url = MinioUtils.getPresignedObjectUrl(objectKey, bucket);
        String url = url_prefix + objectKey;
        String coverUrl = "";
        String watermarkUrl = "";
        String savePath;
        String mp4Name = "cover.mp4";
        String jpgName = "cover.jpg";
        if (System.getProperty("os.name").toLowerCase().startsWith("win")) {
            savePath = "D:\\download";
        } else {
            savePath = "/nfs/zj-lab-temp";
        }
        MinioUtils.makeFilePath(savePath);
        java.io.File file = new java.io.File(savePath);
        MinioUtils.deleteFile(file);
        System.out.println("fileName:" + fileName);
        System.out.println("savepath:" + savePath);
        System.out.println("objectKey:" + objectKey);
        MinioUtils.download(bucket, objectKey, savePath, fileName);
        String imgPath = savePath + "/" + jpgName;
        String waterMarkPath = savePath + "/" + fileName;
        String type;
        if (fileName.endsWith("mp4") || fileName.endsWith("MP4")) {
            type = "video";
        } else if (ImageUtils.isImage(fileName)) {
            type = "image";
        } else {
            type = "other";
        }
        if (type.startsWith("video")) {
            //String imgSavePath = "/opt/ffmpeg/bin/covr.jpg";
            //FFMPEG.videoCatchImg(mp4Math, imgPath);
            FFMPEGUtil.extract(waterMarkPath, imgPath);
            MinioUtils.uploadFile(bucket, cover, imgPath);
            coverUrl = url_prefix + cover;
            type = StringPool.ONE;
        } else if (type.startsWith("image")) {
            type = StringPool.ZERO;
            if (isCompress) {
                String coverKey = UUID.randomUUID() + "";
                MinioUtils.uploadByInputStream(bucket, coverKey, ImageUtils.compressImages(new URL(url)));
                coverUrl = url_prefix + coverKey;
            } else {
                coverUrl = url;
            }
            HashMap<String, String> dto = new HashMap<String, String>();
            dto.put("input_path", url);// 必填
            dto.put("video_converted_path", waterMarkPath);// 必填
            //logo = "D\\\\:/station_group/实验室/logo/zjlab.png";
            dto.put("logo", logo);
            dto.put("height", String.valueOf(height));
            FFMPEGUtil.watermark(dto);
            MinioUtils.uploadFile(bucket, watermark, waterMarkPath);
            watermarkUrl = url_prefix + watermark;
        } else {
            type = "2";
        }

        if (StringUtils.isNotBlank(websiteId)) {
            ResultVO resultVO = websiteClient.queryById(Integer.parseInt(websiteId));
            JSONObject json = JSONObject.parseObject(JSONObject.toJSONString(resultVO));
            Website website = JSONObject.parseObject(json.getString("data"), Website.class);
            if (website.getUrlStatus() == 1) {
                url = website.getWebsiteUrl() + StringPool.SLASH + bucket + StringPool.SLASH + objectKey;
                coverUrl = coverUrl.replace(url_prefix, website.getWebsiteUrl() + StringPool.SLASH + bucket + StringPool.SLASH);
            }
        }
        Long id = insertFile(fileName, objectKey, url, belongKey, type, coverUrl, watermarkUrl, websiteId);
        jsonObject.put(Constant.FILE_NAME, fileName);
        jsonObject.put(Constant.FILE_NAME_IN_SERVER, objectKey);
        jsonObject.put(Constant.URL, url);
        jsonObject.put(Constant.COVERURL, coverUrl);
        jsonObject.put("id", id);
        return jsonObject;
    }

    private Long insertFile(String fileName, String objectKey, String url, String belongKey, String type, String coverUrl, String watermarkUrl, String websiteId) {
        File fileEntity = new File();
        fileEntity.setBucket(bucket);
        fileEntity.setCreateTime(new Date());
        fileEntity.setFileName(fileName);
        fileEntity.setFileNameInServer(objectKey);
        fileEntity.setUrl(url);
        fileEntity.setIsDeleted(NumberConstant.NUMBER_0);
        fileEntity.setType(type);
        fileEntity.setCoverUrl(coverUrl);
        fileEntity.setWatermarkUrl(watermarkUrl);
        String currentUserId = TokenUserUtil.getCurrentUserId();
        if (currentUserId != null) {
            ResultVO<?> userById = userClient.getUserById(currentUserId);
            JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(userById));
            User user = JSONObject.parseObject(jsonObject.getString("data"), User.class);
            fileEntity.setUploader(user.getUsername());
        }
        if (StringUtils.isNotBlank(belongKey)) {
            fileEntity.setBelongKey(belongKey);
        } else {
            fileEntity.setBelongKey(StringPool.ONE);
        }
        if (websiteId != null) {
            fileEntity.setWebsiteId(websiteId);
        } else {
            websiteId = WebsiteUtil.getWebsiteId();
            if (websiteId != null) {
                fileEntity.setWebsiteId(websiteId);
            }
        }
        fileMapper.insert(fileEntity);
        return fileEntity.getId();
    }

    /**
     * 通过url上传文件
     *
     * @return
     * @throws Exception Exception
     */

    public JSONObject uploadByUrl(String uri, String websiteId) throws Exception {
        String fileName = uri.substring(uri.lastIndexOf("/") + 1);
        String objectKey = UUID.randomUUID() + uri.substring(uri.lastIndexOf("."));
        InputStream inputStreamFromUrl = getInputStreamByUrl(uri);
        // 把文件放到minio的boots桶里面
        MinioUtils.uploadInputStream(bucket, objectKey, inputStreamFromUrl);
        Integer height = 0;
        if (!(fileName.endsWith("mp4") || fileName.endsWith("MP4"))) {
            height = getImgWH(uri)[1];
        }
        return getFile(null, fileName, objectKey, height, websiteId, false);
    }


    /**
     * 根据地址获得数据的输入流
     *
     * @param strUrl 网络连接地址
     * @return url的输入流
     */
    public static InputStream getInputStreamByUrl(String strUrl) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(strUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(20 * 1000);
            final ByteArrayOutputStream output = new ByteArrayOutputStream();
            IOUtils.copy(conn.getInputStream(), output);
            return new ByteArrayInputStream(output.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (conn != null) {
                    conn.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 上传文件
     *
     * @return
     * @throws Exception Exception
     */

    public JSONObject commonUpload(HttpServletRequest request) throws Exception {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        MultipartFile file = multipartRequest.getFile("file");
        String fileName = file.getOriginalFilename();
        System.out.println(fileName);
        String objectKey = UUID.randomUUID() + fileName.substring(fileName.lastIndexOf("."));
        String common_url_prefix = "http://10.101.116.3:9000/common/";
        String url = common_url_prefix + objectKey;
        // 把文件放到minio的boots桶里面
        MinioUtils.uploadInputStream("common", objectKey, file);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(Constant.FILE_NAME, fileName);
        jsonObject.put(Constant.FILE_NAME_IN_SERVER, objectKey);
        jsonObject.put(Constant.URL, url);
        return jsonObject;
    }


}





